/*
 * Copyright 2011-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sabayframework.mem;

import org.sabayframework.activity.Activity;
import org.sabayframework.channel.Channel;

/**
 * Interface of transaction in memory space. 
 * @author Alex Antonau
 * */
public interface Transaction {
	
	/**
	 * Locking strategy defines how a transaction handles concurrent modifications.
	 * */
	public enum Locking {
		/**
		 * Last Writer Wins strategy. No locks, commit will always overwrite existing data.
		 * */
		NONE,
		/**
		 * Optimistic locking strategy. No locks on read/write operations. Commit will fail 
		 * if an updated record was modified concurrently by another transaction. 
		 * */
		OPTIMISTIC,
		/**
		 * Pessimistic locking strategy. Read/write operations acquire write locks on
		 * records and then commit/roll back releases these locks. During this time concurrent 
		 * record read/write operations will be blocked.  
		 * */
		PESSIMISTIC
	}
	public enum Status {
		/**
		 * Transaction is active.
		 * */
		ACTIVE, 
		/**
		 * Transaction was successfully committed.
		 * */
		COMMIT, 
		/**
		 * Transaction was rolled back.
		 * */
		ROLLBACK;
	}
	
	long getId();

	/**
	 * Check whether record(s) with given id(s) exists.
	 * @param input channel for record id(s).
	 * @param output channel for booleans, true if space contains a record; false - otherwise.
	 * */
	void contains(Channel<Long> input, Channel<Boolean> output);
	
	/**
	 * Execute an activity for records with given id(s).
	 * @param activity activity
	 * @param input channel for record id(s).
	 * @param output channel for activity output
	 * */
	<I extends Memorizable, O> void execute(Class<I> objectClass, Activity<I,O> activity, Channel<Long> input, Channel<O> output);
	
	/**
	 * Read records with given id(s). For objects that weren't found empty Memorizable objects are returned.
	 * @param input channel for record id(s).
	 * @param output channel for records
	 * */
	<T extends Memorizable> void read(Class<T> objectClass, Channel<Long> input, Channel<T> output);
	
	/**
	 * Write records into storage.
	 * @param input channel for modified records
	 * */
	<T extends Memorizable> Channel<Void> write(Channel<T> input);

	/**
	 * Deletes records with given id(s) from storage.
	 * @param input channel for record id(s).
	 * */
	Channel<Void> delete(Channel<Long> input);
	
	/**
	 * Commit changes in the transaction.
	 * */
	Channel<Void> commit() ;
	/**
	 * Roll back changes in the transaction.
	 * */
	Channel<Void> rollback();
	
	/**
	 * Returns transaction status.
	 * */
	Status getStatus();
	
}
